package com.lin.nio.buffer;


import org.junit.Test;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * a new buffer
 * 原始状态：position=0，写限制limit=capacity
 * flip()切换成读模式：position=0，读限制limit=当前position
 * clear()切换写模式：position=0，写限制limit=capacity
 * <p>
 * int readByte = channel.read(buffer)
 * buffer.put()
 */
public class ByteBufferExample {

    @Test
    public void writeToBuffer() {
        // 0data
        try (RandomAccessFile outFile = new RandomAccessFile("E:\\ljl\\net-programme\\src\\main\\resources\\data-out.txt", "rw")) {
            // 1Channel
            FileChannel fileChannel = outFile.getChannel();

            // 2Buffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(10);

            do {
                // data -> channel -> buffer
                int fileRead = fileChannel.read(byteBuffer);
                System.out.println("读到的字节数：" + fileRead);
                if (fileRead == -1) break;


                // 读取ByteBuffer中的数据
                byteBuffer.flip();
                while (byteBuffer.hasRemaining()) {
                    byte b = byteBuffer.get();
                    System.out.println(((char) b));
                }
                byteBuffer.clear();
            } while (true);

        } catch (IOException e) {
        }
    }

    /**
     * 网络上有多条数据发送给服务端，数据之间使用 \n 进行分隔
     * 但由于某种原因这些数据在接收时，被进行了重新组合，例如原始数据有3条为
     * <p>
     * * Hello,world\n
     * * I'm zhangsan\n
     * * How are you?\n
     * <p>
     * 变成了下面的两个 byteBuffer (黏包，半包)
     * <p>
     * * Hello,world\nI'm zhangsan\nHo
     * * w are you?\n
     * <p>
     * 现在要求你编写程序，将错乱的数据恢复成原始的按 \n 分隔的数据
     */
    @Test
    public void bufferPractice() {
        ByteBuffer source = ByteBuffer.allocate(32);
        source.put("Hello,world\nI'm zhangsan\nHo".getBytes()); // 第一条数据
        openData(source); // 解数据


        source.put("w are you?\n".getBytes()); // 第二条数据
        openData(source); // 解数据
    }


    /**
     * 解析数据
     * @param source
     * @param temp
     */
    private void openData(ByteBuffer source) {
        int position = source.position();

        source.flip();
        int flag = 0; // 记录换行符位置
        for (int i = 0; i < position; i++) {
            if (((char) source.get(i)) == '\n') { // 说明是完整的数据
                byte[] dst = new byte[i - flag];
                source.get(dst, 0, i - flag);
                System.out.println("解析好的数据：" + new String(dst)); // 取到数据
                flag = i;
                source.get(); // position+1 跳过换行符
            }
        }

        source.position(flag + 1);
        source.compact();
    }

}
